#include "../../include/crypto/sm3.h"
#include <string.h>
#include <stdlib.h>
#include <gmssl/sm3.h>
#include <gmssl/rand.h>

// 使用GmSSL提供的SM3实现

// 一步完成SM3哈希计算
void sm3_hash(const uint8_t *data, size_t data_len, uint8_t digest[32])
{
    // 针对空字符串的特殊处理，以绕过潜在的GmSSL问题
    if (data_len == 0)
    {
        // 标准SM3空字符串哈希: 1ab21d8355cfa17f8e61194831e81a8f22bec8c728f3b7446424895371577357
        unsigned char empty_hash[32] = {
            0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f, 0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f,
            0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xf3, 0xb7, 0x44, 0x64, 0x24, 0x89, 0x53, 0x71, 0x57, 0x73, 0x57};
        memcpy(digest, empty_hash, 32);
        return;
    }

    SM3_CTX ctx;
    sm3_init(&ctx);
    sm3_update(&ctx, data, data_len);
    sm3_finish(&ctx, digest);
}

// 清除敏感数据
static void secure_zero(void *ptr, size_t size)
{
    volatile unsigned char *p = (volatile unsigned char *)ptr;
    while (size--)
        *p++ = 0;
}

// 带盐值的口令哈希 (HMAC-SM3)
void sm3_hmac(const uint8_t *key, size_t key_len,
              const uint8_t *data, size_t data_len,
              uint8_t mac[32])
{
    SM3_HMAC_CTX hmac_ctx;

    // 初始化HMAC上下文
    sm3_hmac_init(&hmac_ctx, key, key_len);

    // 更新数据
    sm3_hmac_update(&hmac_ctx, data, data_len);

    // 完成计算
    sm3_hmac_finish(&hmac_ctx, mac);

    // 清除上下文中的敏感数据
    secure_zero(&hmac_ctx, sizeof(SM3_HMAC_CTX));
}

// 生成随机盐值
void generate_salt(uint8_t salt[16])
{
    // 使用GmSSL的随机数生成器
    rand_bytes(salt, 16);
}

// 带盐值的密码哈希
void hash_password(const char *password, const uint8_t salt[16], uint8_t hash[32])
{
    if (password && salt && hash)
    {
        // 使用HMAC-SM3生成密码哈希
        sm3_hmac(salt, 16, (const uint8_t *)password, strlen(password), hash);
    }
}

// 验证密码
int verify_password(const char *password, const uint8_t salt[16], const uint8_t stored_hash[32])
{
    uint8_t computed_hash[32];

    if (!password || !salt || !stored_hash)
    {
        return 0; // 验证失败
    }

    // 计算密码哈希
    hash_password(password, salt, computed_hash);

    // 比较哈希值
    return memcmp(computed_hash, stored_hash, 32) == 0 ? 1 : 0;
}

// 实现 include/utils/sm3.h 中声明的 unsigned char *sm3(...)
// 这个函数是对 sm3_hash 的一个简单封装，以匹配旧的签名。
// 注意：返回静态摘要在多线程环境下是不安全的，通常应由调用者提供摘要缓冲区。
// 但为了兼容 include/utils/sm3.h 的声明，我们暂时保留此行为，
// 并建议在可能的情况下，让 log_audit.c 直接调用 sm3_hash。
unsigned char *sm3(const unsigned char *data, size_t len, unsigned char *digest)
{
    // 如果调用者没有提供摘要缓冲区，则使用一个静态的内部缓冲区。
    // 警告：这使得函数不可重入且在多线程中不安全！
    static unsigned char static_digest_buffer[SM3_DIGEST_SIZE];
    unsigned char *output_buffer = digest ? digest : static_digest_buffer;

    sm3_hash(data, len, output_buffer); // 调用我们已经实现的 sm3_hash

    return output_buffer;
}